#include "StdAfx.h"
#include "stackds.h"

CStackDS::CStackDS(int nBlockSize)
	:Buffer(NULL),Pointer(0),BlockSize(nBlockSize),BlockCount(0),
	CleanOnPop(TRUE)
{
}

CStackDS::~CStackDS(void)
{
	delete[] Buffer;
}

BYTE CStackDS::Pop(void)
{
	if(Pointer)
	{
		BYTE value = Buffer[--Pointer];
		if(CleanOnPop) CleanToFit();
		return value;
	}
	else
		return 0xFF;
}

void CStackDS::Push(BYTE value)
{
	if(Pointer == BlockCount*BlockSize)
	{
		BlockCount++;
		PBYTE newBuffer = new BYTE[BlockCount*BlockSize];
		if(Buffer)
		{
			for(int n=0; n<(BlockCount-1)*BlockSize; n++)
				newBuffer[n] = Buffer[n];
			delete[] Buffer;
		}
		Buffer = newBuffer;
	}
	Buffer[Pointer++] = value;
}

int CStackDS::GetCount()
{
	return Pointer;
}

BYTE CStackDS::GetAt(int n)
{
	return Buffer[n];
}

void CStackDS::SetCleanOnPop(BOOL value)
{
	CleanOnPop = value;
}

void CStackDS::CleanToFit()
{
	if(Buffer && Pointer<=(BlockCount-1)*BlockSize && BlockCount!=1)
	{
		int BlocksNeeded = Pointer/BlockSize;
		if(Pointer%BlockSize) BlocksNeeded++;
		PBYTE newBuffer = new BYTE [BlocksNeeded*BlockSize];
		for(int n=0; n<BlocksNeeded*BlockSize; n++)
			newBuffer[n] = Buffer[n];
		delete[] Buffer;
		Buffer = newBuffer;
	}
}

BOOL CStackDS::IsEmpty(void)
{
	return Pointer == 0;
}

BYTE CStackDS::GetHead()
{
	return (Pointer==0)?0xFF:Buffer[Pointer-1];
}

#ifdef _DEBUG
void CStackDS::Dump(CDumpContext &dc)
{
	CObject::Dump(dc);
	dc<<"BlockSize: "<<BlockSize;
	if(Pointer)
	{
		dc<<" Blocks: "<<BlockCount;
		dc<<" Count: "<<Pointer;
		dc<<" Head: "<<int(Buffer[Pointer-1]);
		dc<<"'"<<Buffer[Pointer-1]<<"'";
	}
	else
		dc<<" Stack is empty";
}
#endif

